package com.hongding.sealcenter.util;

import cn.com.hongding.seal.sign.util.CertUtils;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.security.*;
import java.security.cert.X509Certificate;
import java.util.Base64;

/**
 * PFX证书工具类
 * jar包依赖中 apply-cert-base-1.0.0.jar 包中 CertUtils 工具类也有类似的功能
 */
public class PfxCertUtil {


    /**
     * 获取 KeyStore 实例
     * @param pkcs12 pfx证书base64字符串
     * @param pfxPassword pfx证书密码
     * @return
     * @throws Exception
     */
    public static KeyStore getKeyStore(String pkcs12, String pfxPassword) throws Exception {
        byte[] bytes = Base64.getDecoder().decode(pkcs12);
        InputStream inputStream = new ByteArrayInputStream(bytes);
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(inputStream, pfxPassword.toCharArray());
        return keyStore;

    }

    /**
     * 获取私钥
     * @param keyStore
     * @param alias 证书别名 （证书序列号）
     * @param pfxPassword 证书密码
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(KeyStore keyStore, String alias, String pfxPassword) throws Exception {
        //获取私钥
        return (PrivateKey) keyStore.getKey(alias, pfxPassword.toCharArray());
    }

    /**
     * 获取私钥
     * @param pkcs12 证书base64字符串
     * @param pfxPassword 证书密码
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String pkcs12, String pfxPassword) throws Exception {
        CertUtils.KeyStoreInfo keyStoreInfo = CertUtils.parseKeyStore(pkcs12, pfxPassword);
        return keyStoreInfo.getPrivateKey();
    }


    /**
     * 获取公钥
     * @param cert 证书
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(X509Certificate cert) throws Exception {
        //获取私钥
        return cert.getPublicKey();
    }



    /**
     * 获取证书
     * @param keyStore
     * @param alias 证书别名 （证书序列号）
     * @return
     * @throws Exception
     */
    public static X509Certificate getCert(KeyStore keyStore,String alias) throws Exception {
        //获取证书
       return  (X509Certificate) keyStore.getCertificate(alias);
    }


    /**
     * pfx签名
     * @param privateKey 私钥
     * @param algorithm 加密方式
     * @param text 待签名数据
     * @return 签名值 base64字符串
     * @throws Exception
     */
    public static String pfxSign(PrivateKey privateKey,String  algorithm,String text) throws Exception {
        byte[] data = text.getBytes();
        Signature signer = Signature.getInstance(algorithm);
        signer.initSign(privateKey);
        signer.update(data);
        byte[] sign = signer.sign();
        return Base64.getEncoder().encodeToString(sign);
    }

    /**
     * pfx验签
     * @param publicKey 公钥
     * @param algorithm 加密方式
     * @param text 原文
     * @param signStr 签名值 base64字符串
     * @return
     * @throws Exception
     */
    public static Boolean verifySign(PublicKey publicKey,String  algorithm,String text,String signStr) throws Exception {
        byte[] data = text.getBytes();
        Signature verifier = Signature.getInstance(algorithm);
        verifier.initVerify(publicKey);
        verifier.update(data);
        byte[] sign = Base64.getDecoder().decode(signStr);
        return verifier.verify(sign);
    }

    public static void main(String[] args) {
        try {
            CertUtils.KeyStoreInfo keyStoreInfo = CertUtils.parseKeyStore(new File("C:\\Users\\admin\\Desktop\\temp.pfx"), "7777");
            X509Certificate certificate = keyStoreInfo.getCertificate();

            PublicKey publicKey = certificate.getPublicKey();
            PrivateKey privateKey = keyStoreInfo.getPrivateKey();
            String text = "hello world";
            String signStr = pfxSign(privateKey, certificate.getSigAlgName(), text);
            System.out.println("签名值："+signStr);
            Boolean verify = verifySign(publicKey, certificate.getSigAlgName(), text, signStr);
            System.out.println("验签结果："+verify);

            System.out.println("证书序列号："+certificate.getSerialNumber().toString(16));
            System.out.println("证书颁发者："+certificate.getIssuerDN().toString());
            System.out.println("证书所有者："+certificate.getSubjectDN().toString());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
